package spider

import (
	"asocrawler/conf"
	"asocrawler/db"
	"asocrawler/tool"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

const (

	/* 小游戏 */
	VivoGameRankDataUrl    = "https://quickgame.vivo.com.cn/api/quickgamecenter/rank/gameList"
	VivoGameOtherDataUrl   = "https://quickgame.vivo.com.cn/api/quickgamecenter/subTopComponents"
	VivoHighQualityDataUrl = "https://quickgame.vivo.com.cn/api/quickgamecenter/highQualityGameList"
	VivoNewGameListDataUrl = "https://quickgame.vivo.com.cn/api/quickgamecenter/newGameList"
	VivoTypeListDataUrl    = "https://quickgame.vivo.com.cn/api/quickgamecenter/typeList"
)

type VivoSpider struct {
	ChannelName  string
	TimeInterval int
	Platform     string
	AppIconMap   map[string]int
}

func NewVivoDriver() (v *VivoSpider) {
	v = &VivoSpider{
		ChannelName:  "vivo",
		Platform:     "H5",
		TimeInterval: 2 * 60 * 60, //两小时采集间隔
		AppIconMap:   make(map[string]int),
	}
	return
}

func (this VivoSpider) Run() {
	go func() {
		this.run()
	}()
}
func (this *VivoSpider) Println(v ...interface{}) {
	var str = fmt.Sprintf("[%s]-[%s]", this.ChannelName, this.Platform)
	if conf.Conf.Debug.Switch {
		str += "-[Debug]"
	}
	log.Println(str, fmt.Sprintln(v...))
}

//新品榜
type vivoNewGameRankData struct {
	Code int `json:"code"`
	Data struct {
		GameList []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"gameList"`
	} `json:"data"`
}

func (this *VivoSpider) collectNewGameRankData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("type", "2")
	req, err := http.NewRequest("GET", VivoGameRankDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoNewGameRankData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectNewGameRankData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectNewGameRankData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "新品榜"
	if len(p.Data.GameList) > 0 {
		for i, d := range p.Data.GameList {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")

			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       1,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//热门榜
type vivoHotGameRankData struct {
	Code int `json:"code"`
	Data struct {
		GameList []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"gameList"`
	} `json:"data"`
}

func (this *VivoSpider) collectHotGameRankData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("type", "1")
	req, err := http.NewRequest("GET", VivoGameRankDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoHotGameRankData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectHotGameRankData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectHotGameRankData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "热门榜"
	if len(p.Data.GameList) > 0 {
		for i, d := range p.Data.GameList {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       1,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//热力排行
type vivoHotRankingData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectHotRankingData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "4914")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoHotRankingData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectHotGameRankData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectHotGameRankData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "热力排行"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       1,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//热门爆款
type vivoPopularData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectPopularData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "10224")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoPopularData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectPopularData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectPopularData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "热门爆款"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//精品游戏
type vivoHighQualityData struct {
	Code int `json:"code"`
	Data struct {
		HighQualityGames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"highQualityGames"`
	} `json:"data"`
}

func (this *VivoSpider) collectHighQualityData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	req, err := http.NewRequest("GET", VivoHighQualityDataUrl, nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoHighQualityData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectHighQualityData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectHighQualityData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "精品游戏"
	if len(p.Data.HighQualityGames) > 0 {
		for i, d := range p.Data.HighQualityGames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			typeName = strings.Trim(typeName, ",")
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//新游推荐
type vivoNewGameRecommendData struct {
	Code int `json:"code"`
	Data struct {
		NewGames []struct {
			Quickgames []struct {
				AppId       int    `json:"appId"`           // 小游戏id
				GameDesc    string `json:"editorRecommend"` // 游戏描述
				GameName    string `json:"gameName"`        // 游戏名称
				GameVersion string `json:"gameVersion"`     // 游戏版本
				Icon        string `json:"icon"`            // 游戏icon
				OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
				PlayCount   int    `json:"playCount"`       // 玩耍次数
				TypeName    string `json:"typeName"`        // 游戏类型
				SubTypes    []struct {
					SubTypeName string `json:"subTypeName"` // 标签名
				} `json:"subTypes"`
			} `json:"quickgames"`
		} `json:"newGames"`
	} `json:"data"`
}

func (this *VivoSpider) collectNewGameRecommendData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	req, err := http.NewRequest("GET", VivoNewGameListDataUrl, nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoNewGameRecommendData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectNewGameRecommendData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectNewGameRecommendData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "新游推荐"
	if len(p.Data.NewGames) > 0 {
		//p.Data.NewGames[0] 为今日数据 接口返回最近一周数据(7天)
		if len(p.Data.NewGames[0].Quickgames) > 0 {
			for i, d := range p.Data.NewGames[0].Quickgames {
				var icon string
				onSaleDate := int64(d.OnSaleDate) / 1000
				typeName := d.TypeName + ","
				for _, t := range d.SubTypes {
					typeName += t.SubTypeName + ","
				}
				typeName = strings.Trim(typeName, ",")
				if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
					icon = d.Icon
					this.AppIconMap[fmt.Sprint(d.AppId)] = 1
				}
				v := db.ApiData{
					AppId:       fmt.Sprint(d.AppId),
					GameDesc:    d.GameDesc,
					GameName:    d.GameName,
					GameVersion: d.GameVersion,
					Icon:        icon,
					OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
					PlayCount:   d.PlayCount,
					TypeName:    typeName,
					DIndex:      i,
					BRank:       0,
				}
				vs = append(vs, v)
			}
		}
	}

	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//男生爱玩
type vivoBoyLikeData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectBoyLikeData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "4932")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoBoyLikeData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectBoyLikeData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectBoyLikeData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "男生爱玩"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//女生爱玩
type vivoGirlLikeData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectGirlLikeData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "4931")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoGirlLikeData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectGirlLikeData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectGirlLikeData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "女生爱玩"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//儿童乐园
type vivoChildrenLikeData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectChildrenLikeData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "4929")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoChildrenLikeData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectChildrenLikeData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectChildrenLikeData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "儿童乐园"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//创意大会
type vivoCreativeData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectCreativeData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "10234")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoCreativeData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectCreativeData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectCreativeData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "创意大会"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//人气精选
type vivoSelectedData struct {
	Code int `json:"code"`
	Data struct {
		Quickgames []struct {
			AppId       int    `json:"appId"`           // 小游戏id
			GameDesc    string `json:"editorRecommend"` // 游戏描述
			GameName    string `json:"gameName"`        // 游戏名称
			GameVersion string `json:"gameVersion"`     // 游戏版本
			Icon        string `json:"icon"`            // 游戏icon
			OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
			PlayCount   int    `json:"playCount"`       // 玩耍次数
			TypeName    string `json:"typeName"`        // 游戏类型
			SubTypes    []struct {
				SubTypeName string `json:"subTypeName"` // 标签名
			} `json:"subTypes"`
		} `json:"quickgames"`
	} `json:"data"`
}

func (this *VivoSpider) collectSelectedData(date string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("topModuleId", "10223")
	req, err := http.NewRequest("GET", VivoGameOtherDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoSelectedData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectSelectedData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectSelectedData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	vType := "人气精选"
	if len(p.Data.Quickgames) > 0 {
		for i, d := range p.Data.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

//获取分类map
type vivoTypeListData struct {
	Code int `json:"code"`
	Data struct {
		Types []struct {
			TypeId   int    `json:"typeId"`
			TypeName string `json:"typeName"`
		} `json:"types"`
	} `json:"data"`
}

func (this *VivoSpider) collectTypeListData() (tl map[int]string, err error) {
	tryTimes := 0
re:
	tl = make(map[int]string)
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	req, err := http.NewRequest("GET", VivoTypeListDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoTypeListData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectTypeListData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectTypeListData 多次请求失败,退出")
		return
	}
	if len(p.Data.Types) > 0 {
		for _, d := range p.Data.Types {
			tl[d.TypeId] = d.TypeName
		}
	}
	return
}

//分类数据
type vivoGameTypeData struct {
	Code int `json:"code"`
	Data struct {
		TypeModules struct {
			Quickgames []struct {
				AppId       int    `json:"appId"`           // 小游戏id
				GameDesc    string `json:"editorRecommend"` // 游戏描述
				GameName    string `json:"gameName"`        // 游戏名称
				GameVersion string `json:"gameVersion"`     // 游戏版本
				Icon        string `json:"icon"`            // 游戏icon
				OnSaleDate  int    `json:"onSaleDate"`      // 上架时间  xxxx-xx-xx
				PlayCount   int    `json:"playCount"`       // 玩耍次数
				TypeName    string `json:"typeName"`        // 游戏类型
				SubTypes    []struct {
					SubTypeName string `json:"subTypeName"` // 标签名
				} `json:"subTypes"`
			} `json:"quickgames"`
		} `json:"typeModules"`
	} `json:"data"`
}

func (this *VivoSpider) collectGameTypeData(date, vType, typeId string) (rs db.DbDataResult, err error) {
	tryTimes := 0
re:
	client := &http.Client{}
	data := url.Values{}
	data.Add("imei", "865132047973198")
	data.Add("typeId", typeId)
	req, err := http.NewRequest("GET", VivoTypeListDataUrl+"?"+data.Encode(), nil)
	if err != nil {
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var p vivoGameTypeData
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("string(b):", string(b))
		return
	}
	if p.Code != 0 {
		if tryTimes < 20 {
			this.Println("collectGameTypeData 请求失败,重新请求中", string(b))
			tryTimes++
			goto re
		}
		err = errors.New("collectGameTypeData 多次请求失败,退出")
		return
	}
	vs := []db.ApiData{}
	if len(p.Data.TypeModules.Quickgames) > 0 {
		for i, d := range p.Data.TypeModules.Quickgames {
			var icon string
			onSaleDate := int64(d.OnSaleDate) / 1000
			typeName := d.TypeName + ","
			for _, t := range d.SubTypes {
				typeName += t.SubTypeName + ","
			}
			typeName = strings.Trim(typeName, ",")
			if this.AppIconMap[fmt.Sprint(d.AppId)] == 0 {
				icon = d.Icon
				this.AppIconMap[fmt.Sprint(d.AppId)] = 1
			}
			v := db.ApiData{
				AppId:       fmt.Sprint(d.AppId),
				GameDesc:    d.GameDesc,
				GameName:    d.GameName,
				GameVersion: d.GameVersion,
				Icon:        icon,
				OnSaleDate:  time.Unix(onSaleDate, 0).Format("2006-01-02"),
				PlayCount:   d.PlayCount,
				TypeName:    typeName,
				DIndex:      i,
				BRank:       0,
			}
			vs = append(vs, v)
		}
	}
	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}

func (this *VivoSpider) collectH5(date string) (bool, error) {

	rankTypeList, err := db.QueryRankTypeList(this.ChannelName, this.Platform)
	if err != nil {
		this.Println("collectH5 QueryRankTypeList err:", err)
		return false, err
	}

	rs5, err := this.collectHighQualityData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs5.TablePostfix = rankTypeList[rs5.RankType].TablePostfix
	rs5.RankTypeId = rankTypeList[rs5.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs6, err := this.collectNewGameRecommendData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs6.TablePostfix = rankTypeList[rs6.RankType].TablePostfix
	rs6.RankTypeId = rankTypeList[rs6.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs, err := this.collectNewGameRankData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs.TablePostfix = rankTypeList[rs.RankType].TablePostfix
	rs.RankTypeId = rankTypeList[rs.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs2, err := this.collectHotGameRankData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs2.TablePostfix = rankTypeList[rs2.RankType].TablePostfix
	rs2.RankTypeId = rankTypeList[rs2.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs3, err := this.collectHotRankingData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs3.TablePostfix = rankTypeList[rs3.RankType].TablePostfix
	rs3.RankTypeId = rankTypeList[rs3.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs4, err := this.collectPopularData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs4.TablePostfix = rankTypeList[rs4.RankType].TablePostfix
	rs4.RankTypeId = rankTypeList[rs4.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs7, err := this.collectBoyLikeData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs7.TablePostfix = rankTypeList[rs7.RankType].TablePostfix
	rs7.RankTypeId = rankTypeList[rs7.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs8, err := this.collectGirlLikeData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs8.TablePostfix = rankTypeList[rs8.RankType].TablePostfix
	rs8.RankTypeId = rankTypeList[rs8.RankType].Id

	rs9, err := this.collectChildrenLikeData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs9.TablePostfix = rankTypeList[rs9.RankType].TablePostfix
	rs9.RankTypeId = rankTypeList[rs9.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs10, err := this.collectCreativeData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs10.TablePostfix = rankTypeList[rs10.RankType].TablePostfix
	rs10.RankTypeId = rankTypeList[rs10.RankType].Id
	time.Sleep(100 * time.Millisecond)

	rs11, err := this.collectSelectedData(date)
	if err != nil {
		return false, err
	}
	//获取排行榜ID和表后缀
	rs11.TablePostfix = rankTypeList[rs11.RankType].TablePostfix
	rs11.RankTypeId = rankTypeList[rs11.RankType].Id

	if len(rs.Data) == 0 {
		this.Println("collectNewGameRankData 长度为空")
	} else {
		err = db.SaveData(rs)
		if err != nil {
			return false, err
		}
	}

	if len(rs2.Data) == 0 {
		this.Println("collectHotGameRankData 长度为空")
	} else {
		err = db.SaveData(rs2)
		if err != nil {
			return false, err
		}
	}

	if len(rs3.Data) == 0 {
		this.Println("collectHotRankingData 长度为空")
	} else {
		err = db.SaveData(rs3)
		if err != nil {
			return false, err
		}
	}

	if len(rs4.Data) == 0 {
		this.Println("collectPopularData 长度为空")
	} else {
		err = db.SaveData(rs4)
		if err != nil {
			return false, err
		}
	}

	if len(rs5.Data) == 0 {
		this.Println("collectHighQualityData 长度为空")
	} else {
		err = db.SaveData(rs5)
		if err != nil {
			return false, err
		}
	}

	if len(rs6.Data) == 0 {
		this.Println("collectNewGameRecommendData 长度为空")
	} else {
		err = db.SaveData(rs6)
		if err != nil {
			return false, err
		}
	}

	if len(rs7.Data) == 0 {
		this.Println("collectBoyLikeData 长度为空")
	} else {
		err = db.SaveData(rs7)
		if err != nil {
			return false, err
		}
	}

	if len(rs8.Data) == 0 {
		this.Println("collectGirlLikeData 长度为空")
	} else {
		err = db.SaveData(rs8)
		if err != nil {
			return false, err
		}
	}

	if len(rs9.Data) == 0 {
		this.Println("collectChildrenLikeData 长度为空")
	} else {
		err = db.SaveData(rs9)
		if err != nil {
			return false, err
		}
	}

	if len(rs10.Data) == 0 {
		this.Println("collectCreativeData 长度为空")
	} else {
		err = db.SaveData(rs10)
		if err != nil {
			return false, err
		}
	}

	if len(rs11.Data) == 0 {
		this.Println("collectSelectedData 长度为空")
	} else {
		err = db.SaveData(rs11)
		if err != nil {
			return false, err
		}
	}

	/*-------------------分类区---------------------*/
	tl, err := this.collectTypeListData()
	if err != nil {
		return false, err
	}

	for typeId, typeName := range tl {
		ts, err := this.collectGameTypeData(date, typeName, fmt.Sprint(typeId))

		//获取排行榜ID和表后缀
		ts.TablePostfix = rankTypeList[ts.RankType].TablePostfix
		ts.RankTypeId = rankTypeList[ts.RankType].Id

		if err != nil {
			return false, err
		}
		time.Sleep(100 * time.Millisecond)
		if len(ts.Data) == 0 {
			return false, errors.New(fmt.Sprintf("collectGameTypeData 长度为空,typeName=%s", typeName))
		} else {
			err = db.SaveData(ts)
			if err != nil {
				return false, err
			}
		}
	}

	return true, nil
}

func (this *VivoSpider) collect(date string) (bool, error) {
	var err error
	this.AppIconMap, err = db.GetAppIconMap(this.ChannelName, this.Platform)
	if err != nil {
		this.Println("db.GetAppIconMap error,err=", err)
		return false, err
	}

	bol, err := this.collectH5(date)
	if err != nil {
		this.Println("collectH5 err = ", err)
		return bol, err
	}
	return true, nil

}

func (this *VivoSpider) run() {
	if conf.Conf.Debug.Switch {
		this.Println("vivoH5 小游戏无法采集之前的数据，禁用调试模式！！！")
	} else {
	re:
		fDate := time.Now().Format("2006-01-02")
		this.GetDataByDate(fDate)
		time.Sleep(time.Duration(this.TimeInterval) * time.Second)
		goto re
	}
}

func (this *VivoSpider) GetDataByDate(date string) {
	this.Println("日期:", date, "开始采集数据...")
	succ, err := this.collect(date)
	if succ {
		this.Println("日期:", date, "采集数据完成 稍后再次采集...")
	} else {
		if err == nil {
			this.Println("日期:", date, "数据未更新 稍后重新采集...")
		} else {
			tool.SendWarn("ASO报警-vivoH5爬虫报错", "ASO报警-vivoH5爬虫报错,错误信息："+err.Error())
			this.Println("日期:", date, "出现错误err:", err, "稍后重新采集...")
		}
	}
}
